Skip to content

Make lightcone-cli agent-agnostic: remove Claude Code integration - #168

Open
EiffL wants to merge 18 commits into
mainfrom
decouple_skills
Open

Make lightcone-cli agent-agnostic: remove Claude Code integration#168
EiffL wants to merge 18 commits into
mainfrom
decouple_skills

Conversation

@EiffL

@EiffL EiffL commented Aug 11, 2026

Copy link
Copy Markdown
Member

Linear: LCR-181 · Design: de-bundling design doc . This PR superseeds #161

Summary

This branch removes all Claude Code-specific machinery from lightcone-cli, trimming it down to a plain, agent-agnostic CLI.

Removed:

  • The packaged claude/lightcone/ plugin bundle — skills, agents, hooks, session scripts, templates (first commit)
  • src/lightcone/cli/plugin.py (plugin discovery) and the claude/lightcone wheel force-include / sdist include in pyproject.toml
  • From lc init: the .claude/ bundle install, the project CLAUDE.md stub, the --permissions flag, and PERMISSION_TIERS; its next-steps output now points at editing astra.yaml and running lc run
  • docs/skills/ (10 pages) and docs/user/agent-workflow.md, plus their nav entries
  • tests/test_paper_extraction_caption.py, which imported a script from the deleted skills tree

Kept:

  • The full lc CLI surface (init, run, status, verify, build, export), the Snakemake/Dask engine, and the manifest integrity layer — all unchanged
  • The lc eval harness (deliberately retained; only a stale docstring touched). Note: its loop prompt still references the now-removed /lc-cli skill — evals run fine, but that line is a no-op to revisit.

Docs:

  • User guide, README, architecture, CLI reference, and contributing pages rewritten to describe only the CLI; the getting-started tutorial now walks through writing astra.yaml and the analysis scripts by hand (example spec validated with astra validate, fixing previously invalid placeholder syntax)
  • Fixed stale claims encountered along the way: docs/api/site_registry.md called the module orphaned (it's used by lc init, engine.scratch, engine.container); docs/contributing/testing.md carried an obsolete "lc eval not registered" workaround

Test plan

  • uv run pytest — 388 passed
  • uv run ruff check src/ tests/ and uv run mypy src/ — clean
  • uv build --wheel — builds; no claude/plugin files in the wheel
  • just docs — site builds with no errors, no dead links to removed pages

🤖 Generated with Claude Code

https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ

EiffL and others added 3 commits August 11, 2026 14:11
lc init no longer installs a .claude/ plugin bundle, writes a project
CLAUDE.md, or takes --permissions; the plugin discovery module, the
wheel force-include, and the skills/agent-workflow docs are removed.
The lc eval harness is kept.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
init now creates what's missing, repairs the managed .gitignore block
and --scratch override, and never overwrites user files; a directory
that already holds an astra.yaml is adopted instead of rejected.
--check reports drift without writing (exit 1 when not converged);
--json emits {converged, created, repaired, unchanged, warnings}.

The spec scaffold now calls astra's boilerplate helper directly:
astra init's callback refuses non-empty directories and overwrites
.gitignore, both wrong for convergence.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
Falls back to the private helper on astra-tools releases that predate
LightconeResearch/astra-tools#99.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
EiffL added a commit to LightconeResearch/astra-tools that referenced this pull request Aug 11, 2026
## Summary

Companion to LightconeResearch/lightcone-cli#168, which turns `lc init`
into an idempotent converger. This PR brings `astra init` in line with
the same philosophy and exposes the scaffold writer as a public API.

**`astra init` is now an idempotent converger.** Each run creates
whatever is missing (`astra.yaml` + `universes/baseline.yaml`,
`universes/`, `src/`, `.gitignore`, git repo) and never overwrites
existing files. The old refusals — "already an ASTRA project" and
"directory not empty" — are gone; those directories are adopted instead.
Two new flags, matching the `lc init` contract:

- `--check` — report what a run would create, write nothing, exit 1 when
not converged
- `--json` — emit the report as `{converged, created, repaired,
unchanged, warnings}`

One deliberate subtlety: the boilerplate `astra.yaml` and
`universes/baseline.yaml` are treated as a single unit keyed on
`astra.yaml` presence — a user-authored spec never gets the boilerplate
baseline written next to it (it references the boilerplate's example
decision).

**`create_boilerplate(directory)` is public.** It writes only
`universes/`, `src/`, `astra.yaml`, and `universes/baseline.yaml` — no
`.gitignore`, no git init, no policy — so downstream tools
(lightcone-cli's `lc init`) can scaffold the spec under their own
conventions. `astra init` delegates to it.

## Test plan

- [x] New tests: adoption of non-empty directories (existing files and
`.gitignore` untouched), idempotent re-run (byte-identical tree,
`converged: true`), user-spec-without-baseline invariant, `--check`
drift/no-write/exit-code behavior, `create_boilerplate` contents and
side-effect freedom
- [x] `uv run pytest` — 221 passed, 21 skipped (existing
scaffold-content, validation, and git tests unchanged and green)
- [x] `ruff check` clean
- [x] Manual smoke test: converge into a non-empty directory, re-run
with `--json`, `--check` exit codes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
EiffL and others added 8 commits August 11, 2026 16:06
Tracks LightconeResearch/astra-tools#100: the spec scaffold no longer
creates an empty src/ — where code lives is the user's choice.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
An empty gitignored placeholder is invisible in git, so it carried no
hint after clone. The README says outputs land in
results/<universe>/<output_id>/ via lc run and must not be written by
hand; the gitignore block becomes results/* + !results/README.md so
the one file stays tracked while outputs remain ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
The venv exists to run analysis code; `lc` lives outside it (uv tool
install), and a second copy inside shadowed it with whatever version
PyPI resolved — unpinned, so even released drivers got skew. The venv
now installs requirements.txt (which the old venv never did), and the
execution-stack pin moves from requirements.txt into its own
Containerfile layer, where the image — the one place that genuinely
needs lightcone-cli — still gets it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
requirements.txt changes on every dependency edit; the lightcone-cli
layer is the heavy one (snakemake, dask, distributed, dask-gateway)
and its pin rarely changes. Ordering it first keeps it cached across
requirements edits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
Nothing ever read the baked copy: recipes run against the live project
tree (bind-mounted -v $PWD -w $PWD locally, shared filesystem on a
hub). Meanwhile compute_image_tag hashes every COPY source, so the
copy made each code edit change the tag and force a rebuild. The image
is now a pure environment — the tag moves only when the Containerfile
or dependency files change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
With the image now a pure environment, directory COPY sources
(COPY . ., COPY src/) would only bake in a copy nothing executes —
recipes run against the live project tree — while forcing a full tree
hash on every tag computation and a rebuild on every code edit. They
now raise ContainerBuildError with guidance. Removes _COPY_DIR_EXCLUDE,
_hash_dir_into, and _copy_tree_filtered (~60 lines); file COPY sources
remain fully supported.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
Three moves cover the ten confirmed findings:

- One error boundary: CloudBuildError now subclasses
  ContainerBuildError, and the click group translates
  ContainerBuildError into a clean ClickException — lc run/build/
  status/cloudbuild all stop leaking tracebacks (findings 1-3).
- The converger repairs what lightcone wrote: _converge_file gains a
  repair(text)->str|None hook; legacy scaffold artifacts migrate
  forward (old Containerfile template -> current, lightcone-cli pin
  stripped from requirements.txt, blanket results/ gitignore rule
  narrowed so results/README.md stays tracked), and the warnings
  channel now carries what init sees but must not fix — hand-edited
  Containerfiles with directory COPYs (via the shared
  directory_copy_sources detector) and unparseable lightcone.yaml
  (findings 4, 5, 7, 8).
- Point fixes: eval loop prompt no longer invokes deleted skills;
  src/ scaffold claims removed from docstring and troubleshooting;
  the astra.yaml container: rewrite is a top-level-line regex with a
  warning fallback and a CI test pinning the result; the astra import
  fallback no longer swallows nested ImportErrors (findings 6, 9, 10).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
Projects from previous releases are not migrated: the verbatim
Containerfile upgrade, requirements pin-stripping, and blanket
results/ gitignore rewrite are gone along with their tests. What
remains is version-agnostic: the error boundary, the gitignore
append-once repair (adoption, not migration), the lightcone.yaml
parse guard, and the directory-COPY advisory warning.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
@EiffL EiffL mentioned this pull request Aug 11, 2026
2 tasks
EiffL added a commit that referenced this pull request Aug 11, 2026
## Summary

Split out from #168 so the deployment switch can land (and current-main
docs can be redeployed) independently of the CLI changes.

- **Release-gated deploys**: `docs-deploy.yml` now triggers on `release:
published` — the same moment as the PyPI publish — instead of every push
to main, so docs.lightconeresearch.org never documents behavior `pip
install lightcone-cli` can't deliver yet. `workflow_dispatch` remains
for manual intermediate deploys (typo fixes, clarifications) from the
Actions tab.
- **One hosting target**: consolidates on GitHub Pages. `wrangler.jsonc`
(added by the Cloudflare bot's autoconfig PR #118, not a design
decision) is deleted; the Cloudflare Workers deployment retires.
- `check-docs.yml` is untouched: docs are still build-validated on every
merged PR — they just don't ship until a release or a manual dispatch.

## Manual follow-ups (dashboard-side, can't be done from the repo)

1. Cloudflare: disconnect this repo from Workers Builds and retire the
`lightcone-cli` worker.
2. Cloudflare DNS: CNAME `docs.lightconeresearch.org` →
`lightconeresearch.github.io` (DNS-only while GitHub validates).
3. GitHub Pages settings: set the custom domain, then enable Enforce
HTTPS.

After merging, run the workflow once manually to deploy current main to
Pages.

## Test plan

- [x] Docs build (`zensical build`) unchanged and green
- [x] Workflow YAML: triggers are `release: published` +
`workflow_dispatch`; build/deploy jobs otherwise identical to what ran
before

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
EiffL and others added 4 commits August 11, 2026 22:42
Delete the lightcone.eval subpackage (Daytona sandbox, harness,
graders, report, models, lc eval CLI) and its tests, deps, and config.
The eval is now a single workflow job: scaffold a project with lc init,
overlay the task seed, run Claude Code headlessly with evals/prompt.md
(astra skill installed from the LightconeResearch/agent-skills plugin
marketplace), then gate on astra validate + lc status --json.

The prompt carries a lightcone-cli primer (lc run / lc status, results
layout, manifest rules) since the skill system no longer ships with the
CLI. Also fix the snae seed spec: dependency declarations moved from
recipe.inputs to Output.inputs in the current astra schema.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown

✅ Eval

Metric Value
Outputs check success
Agent run success
Turns 52
Tool calls 50
Cost $1.08
Agent wall time 5m11s
Model claude-sonnet-5
lc status

Universe baseline
  ✓ ok      best_fit
  ✓ ok      hubble_diagram
  ✓ ok      residuals

Full trace: agent-trace artifact on this run.

The eval-project artifact keeps hidden files for the provenance
manifests, so explicitly exclude the project .venv and .snakemake
scratch. Configure a global git identity at the start of project
setup so agent commits don't fail on the fresh runner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016EL5bESx3CqfMNZNPA1KHJ
@EiffL

EiffL commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

@claude can you review this PR? one note on the intent, we want to make lightcone cli a completely standalone cli, intended to be used by agents and humans, but decoupled completely from claude code or other harnesses.

@claude

claude Bot commented Aug 11, 2026

Copy link
Copy Markdown

Claude finished @EiffL's task in 2m 56s —— View job


Review: agent-agnostic decoupling

  • Gather context (PR description, changed files list)
  • Review core CLI changes (src/lightcone/cli/commands.py, removal of plugin.py)
  • Review pyproject.toml / packaging changes
  • Review eval harness changes (.github/scripts/trace_digest.py, evals/, .github/workflows/eval.yml)
  • Review docs changes for consistency
  • Check for lingering references to removed Claude Code machinery
  • Post final review

Confirmed the intent: this cleanly severs lightcone-cli from Claude Code. claude/lightcone/ (skills, agents, hooks, templates), src/lightcone/cli/plugin.py, the wheel force-include/sdist entries, --permissions/PERMISSION_TIERS, and docs/skills/ + docs/user/agent-workflow.md are all gone, and I couldn't find any leftover references to .claude/, SKILL.md, --permissions, or claude/lightcone in the product code or shipped docs (the only remaining Claude Code mentions are in the eval harness, which intentionally drives the CLI with Claude Code as a test agent — that's fine, it's not part of the shipped package).

Findings

  1. PR description is out of date vs. the actual diff. The "Kept" section says "The lc eval harness (deliberately retained; only a stale docstring touched)", but the diff fully deletes src/lightcone/eval/ (cli.py, harness.py, sandbox.py, graders.py, models.py, report.py, build.py, __init__.py) and the eval dependency group in pyproject.toml, replacing it with a GitHub Actions–driven eval (evals/prompt.md + .github/workflows/eval.yml + .github/scripts/trace_digest.py). That's a reasonable design (no Python harness to keep decoupled-agnostic), but it's a materially different/larger change than the description states, and the specific caveat about the /lc-cli skill reference in the loop prompt no longer applies — I couldn't find that reference anywhere in the current evals/prompt.md. Worth updating the PR body so reviewers aren't reviewing against a stale summary.

  2. Diff scope is broader than "remove Claude Code integration." Beyond the decoupling itself, this branch (relative to origin/main) also ships an unrelated lc init rewrite (idempotent converger with --check/--json), Containerfile COPY-directory rejection in engine/container.py, and the eval-harness replacement described above. None of that is inherently wrong — the init rewrite in particular was seemingly needed to drop the .claude/-install step cleanly — but it's a lot of surface area for one PR to review together with the stated "just remove Claude Code stuff" intent. Consider calling out in the description which parts are pure removal vs. new behavior (esp. --check/--json on lc init, which is a new agent-facing contract worth reviewing on its own merits).

  3. Nit — docs/cli/init.md correctly documents the removed --target/--existing-project/--sub-analysis/--permissions flags as historical, and I confirmed none of them remain wired up in commands.py. Good.

  4. Couldn't find anything unsound in the new lc init converger logic (_converge/_converge_file helpers, conservative repair-only-if-fix-is-safe pattern) or in trace_digest.py — both look correct on read-through.

Not verified: I wasn't able to run uv run pytest / ruff / mypy in this sandbox (Bash execution requires interactive approval that wasn't available here), so I relied on static review only. The PR description states these were run and pass (388 passed, ruff/mypy clean, wheel builds without claude/ files) — worth a maintainer double-check on CI rather than taking my review as a substitute for that.

Overall: the decoupling itself is thorough and I found no stray references to the removed Claude Code machinery. Main actionable item is tightening the PR description to match the actual (larger) diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant